home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
demos
/
GL
/
buttonfly
/
buttonfly.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
30KB
|
1,287 lines
/*
* Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/* 12/13/91 Modified technique of handling the DO IT selection from the
pop-up menu to eliminate use of qenter() (Marvin Kong, 12/13/91).
*/
/* 4/25/90 Updated to eliminate executing the action twice if the left
or middle mouse button is double-clicked. This is done by using TIMER0
to add events into the queue approximately every 0.5 s, and checking
the amount of time between mouse clicks. If within 1 s, the action
is not performed (Marvin Kong, 4/25/90).
*/
/* 6/26/89 Updated to provide usability on an eight bitplane Personal IRIS.
The following constraints are in affect for the P.I.: 1) Only one button
color is available. This color is taken from the default color definition
in the main .menu file. 2) The eight bitplane version destroys the lower 16
colors of the colormap, so a method was devised to reset the colormap to the
buttonfly colors when the mouse move into the buttonfly window. No action
is taken when the mouse is moved out of the window, however the default
lower 16 colors are reset when buttonfly is exited. 3) Dithered lighting
was not used primarily because of degredation in performance due to the
required Gouraud shading model.
*/
#include <stdio.h>
#include <math.h>
#include <gl/gl.h>
#include <gl/device.h>
#include "event.h"
#include "kurtfont.h"
#include "buttonfly.h"
#include "data.h"
#define X 0
#define Y 1
#define Z 2
short dev,val;
long originx, originy, sizex, sizey;
long s_originx, s_originy, s_sizex, s_sizey;
int flyinflag = 0;
int flyoutflag = 0;
int selectflag = 0;
int exitflag = 0;
int tick = 3; /* counter for timer events (MKK, 4/25/90) */
button_struct *load_buttons(), *which_button();
extern button_struct *new_button(char *);
button_struct *current_buttons=NULL, *selected=NULL;
path_struct *path=NULL;
button_struct *rootbutton;
float *curbackcolor; /* RGBmode current background color */
int cm_backcolor[3]; /* color mode background color (unsigned short) */
int eightbit = 0; /* flag for RGB/colormode */
short *buttonmaparray; /* array to save colormap indexes */
int have_texture = 0;
/* matrix for projecting next set of buttons
on the back of the selected button */
float tv[4][4] = {
{SCREEN, 0.0, 0.0, 0.0},
{0.0, SCREEN, 0.0, 0.0},
{0.0, 0.0, SCREEN, -1.0},
{0.0, 0.0, 0.0, 0.0},
};
main (argc, argv)
int argc;
char *argv[];
{
extern char *getcwd();
void bf_redraw(), bf_exit(int), bf_selecting();
void bf_quick(), bf_fly(), do_popup(), toggle_window();
void flyindraw(), flyoutdraw(), selectdraw();
void parse_args(), doclear();
void cm_map_button_colors();
void cm_restore_colormap();
void cm_save_colormap();
void add_tick(); /* routine to keep time (MKK, 4/25/90) */
void doit_bf_fly(); /* routine to flip button (MKK, 12/13/91) */
rootbutton = new_button("");
rootbutton->cwd = getcwd(NULL, 128);
selected = rootbutton;
parse_args(argc, argv);
selected = NULL;
keepaspect(5, 4);
{
char *t, *strrchr();
winopen((t=strrchr(argv[0], '/')) != NULL ? t+1 : argv[0]);
}
{
char buf[16];
gversion(buf);
have_texture = (strncmp(buf, "GL4DRE",6) == 0);
}
/* here's where we determine if it's eight bit */
/* eightbit = (getplanes() < 12); */
if ((getgdesc(GD_BITS_NORM_DBL_RED)) < 4)
eightbit = TRUE;
/* eightbit = TRUE; /* OMIT! For testing on 24bit only */
getorigin(&originx, &originy);
getsize(&sizex, &sizey);
subpixel(TRUE);
dither(FALSE);
if (eightbit) {
/* arrays to save color indexed for eight bitplane */
buttonmaparray = (short *)malloc(3 * 16 * sizeof(short));
doublebuffer();
gconfig();
cm_map_button_colors();
cm_save_colormap(buttonmaparray,0,15);
} else {
doublebuffer();
RGBmode();
gconfig();
if (getgdesc(GD_MULTISAMPLE) == 1) {
zbsize(0);
mssize(16,32,0);
gconfig();
if (getgconfig(GC_MS_SAMPLES) <= 4) {
zbsize(32);
mssize(0,0,0);
gconfig();
}
}
lmdef(DEFMATERIAL, 1, 0, mat);
lmdef(DEFLIGHT, 1, 0, light1);
lmdef(DEFLIGHT, 2, 0, light2);
lmdef(DEFLMODEL, 1, 0, light_model);
curbackcolor=rootbutton->backcolor;
}
shademodel(FLAT);
backface(TRUE);
qdevice(REDRAW);
add_event(ANY, REDRAW, ANY, bf_redraw, 0);
qdevice(ESCKEY);
/*
* Ill-behaved programs that exit on ESC down can make buttonfly
* exit accidently with the ESC up event. bf_exit will look for
* both a down and an up event before exiting.
*/
add_event(ANY, ESCKEY, DOWN, bf_exit, (void *)0);
add_event(ANY, ESCKEY, UP, bf_exit, (void *)1);
qdevice(WINQUIT);
qdevice(WINSHUT);
/*
* The 2 passed to bf_exit means exit immediately. See discussion
* of ESCKEY handling above.
*/
add_event(ANY, WINQUIT, ANY, bf_exit, (void *)2);
qdevice(MIDDLEMOUSE);
tie(MIDDLEMOUSE, MOUSEX, MOUSEY);
add_event(ANY, MIDDLEMOUSE, DOWN, bf_selecting, 0);
add_event(ANY, MIDDLEMOUSE, UP, bf_quick, 0);
qdevice(LEFTMOUSE);
tie(LEFTMOUSE, MOUSEX, MOUSEY);
add_event(ANY, LEFTMOUSE, DOWN, bf_selecting, 0);
add_event(ANY, LEFTMOUSE, UP, bf_fly, 0);
qdevice(RIGHTMOUSE);
tie(RIGHTMOUSE, MOUSEX, MOUSEY);
add_event(ANY, RIGHTMOUSE, DOWN, do_popup, 0);
qdevice(SPACEKEY);
add_event(ANY, SPACEKEY, UP, toggle_window, 0);
if (eightbit) {
qdevice(INPUTCHANGE);
add_event(ANY, INPUTCHANGE, 1, cm_restore_colormap, 0);
}
add_update(&flyinflag, flyindraw, 0);
add_update(&flyoutflag, flyoutdraw, 0);
add_update(&selectflag, selectdraw, 0);
qdevice(TIMER0); /* Add event into */
add_event(ANY, TIMER0, ANY, add_tick, 0); /* queue every 30 */
noise(TIMER0,30); /* TIMER events. */
mmode(MPROJECTION);
perspective(450, 5.0/4.0, THICK, 9.0);
translate(0.0, 0.0, -5.0/4.0);
mmode(MVIEWING);
loadmatrix(idmat);
doclear();
draw_buttons(current_buttons);
swapbuffers();
while(exitflag == FALSE)
{
event();
}
gexit();
exit(0);
}
void do_action(char * act)
{
int stat;
stat = fork();
if (stat != 0)
{
if (stat < 0)
perror("Buttonfly: Trying to fork");
return;
}
system(act);
exit(0);
}
void parse_args(argc, argv)
int argc;
char **argv;
{
if (argc > 2) {
fprintf(stderr, "usage: %s [infile]\n", argv[0]);
exit(1);
} else if (argc == 2) {
FILE *fp;
if ((fp = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "%s: can't open file %s\n",
argv[0], argv[1]);
exit(1);
}
current_buttons = load_buttons(fp);
fclose(fp);
} else {
FILE *fp;
if ((fp = fopen(".menu", "r")) == NULL) {
fprintf(stderr, "%s: can't find default file .menu\n",
argv[0], argv[1]);
exit(1);
}
current_buttons = load_buttons(fp);
fclose(fp);
}
}
void bf_exit(int flag)
{
void cm_restore_news_colors(void);
static int armed = 0;
switch(flag)
{
case 0:
armed = 1; /* ESC down event; can exit if we get ESC UP */
break;
case 1:
if (armed == 0)
break;
/* If are armed, will fall through to exit case */
case 2:
if (eightbit)
cm_restore_news_colors();
exitflag = TRUE;
break;
}
}
void bf_selecting()
{
short mx, my;
qread(&mx);
qread(&my); /* Yank off queue */
if (flyinflag || flyoutflag) return;
/*selectflag = TRUE;*/ /* Don't update button if a */
if( tick > 2 ) selectflag = TRUE; /* double-click (MKK, 4/25/90). */
flyinflag = flyoutflag = FALSE;
}
/*
* Middle mouse up == quick selection, no flipping
*/
void bf_quick()
{
short mx, my;
qread(&mx);
qread(&my); /* Yank off queue */
if (flyinflag || flyoutflag) return;
selectflag = flyinflag = flyoutflag = FALSE;
selected = which_button(mx, my);
if (selected) {
push_button(selected);
if (selected->forward) {
add_button_to_path(current_buttons, selected);
current_buttons = selected->forward;
}
else if (path) {
chdir(path->button->cwd);
}
else chdir(rootbutton->cwd);
selected = NULL;
} else if (path) {
path_struct *step;
if( tick < 2 ) /* This was added to */
return; /* eliminate double-clicks */
else /* (MKK, 4/25/90). */
tick = 0;
selected = path->button;
draw_selected_button(selected, 1.0);
selected = NULL;
current_buttons = path->current_buttons;
step = path;
path = path->back;
free(step);
if (path) {
curbackcolor = path->button->backcolor;
chdir(path->button->cwd);
} else {
curbackcolor = rootbutton->backcolor;
chdir(rootbutton->cwd);
}
}
bf_redraw();
}
void bf_fly()
{
short mx, my;
qread(&mx);
qread(&my); /* Yank off queue */
if (flyinflag || flyoutflag) return;
selectflag = flyinflag = flyoutflag = FALSE;
selected = which_button(mx, my);
if (selected) {
push_button(selected);
if (selected->forward) {
add_button_to_path(current_buttons, selected);
flyinflag = TRUE;
} else {
if (path) chdir(path->button->cwd);
else chdir(rootbutton->cwd);
selected = NULL;
bf_redraw();
}
} else if (path) {
path_struct *step;
if( tick < 2 ) /* This was added to */
return; /* eliminate double-clicks */
else /* (MKK, 4/25/90). */
tick = 0;
flyoutflag = TRUE;
selected = path->button;
current_buttons = path->current_buttons;
step = path;
path = path->back;
free(step);
if (path) {
chdir(path->button->cwd);
curbackcolor = path->button->backcolor;
}
else {
chdir(rootbutton->cwd);
curbackcolor = rootbutton->backcolor;
}
}
}
void bf_redraw()
{
reshapeviewport();
getorigin(&originx, &originy);
getsize(&sizex, &sizey);
doclear();
draw_buttons(current_buttons);
swapbuffers();
}
#define BIG 0
#define LITTLE 1
void toggle_window()
{
static int size = LITTLE;
if (size == BIG) {
size = LITTLE;
winposition(s_originx, s_originx + s_sizex,
s_originy, s_originy + s_sizey);
reshapeviewport();
keepaspect(getgdesc(GD_XPMAX), getgdesc(GD_YPMAX));
winconstraints();
getorigin(&originx, &originy);
getsize(&sizex, &sizey);
} else {
size = BIG;
getorigin(&s_originx, &s_originy);
getsize(&s_sizex, &s_sizey);
winposition(0, getgdesc(GD_XPMAX) - 1, 0, getgdesc(GD_YPMAX) - 1);
reshapeviewport();
originx = 0;
originy = 0;
sizex = getgdesc(GD_XPMAX);
sizey = getgdesc(GD_YPMAX);
}
}
void do_popup()
{
short mx, my;
button_struct *b;
void do_buttons_menu();
qread(&mx);
qread(&my);
b = which_button(mx, my);
if (b) {
do_buttons_menu(b, mx, my);
} else if (path) {
do_buttons_menu(path->button, mx, my);
} else if (rootbutton->popup) {
do_buttons_menu(rootbutton, mx, my);
}
}
void do_buttons_menu(b, mx, my)
button_struct *b;
short mx, my;
{
long menu;
int i, num;
char t[128];
popup_struct *scan;
menu = newpup();
if (b != rootbutton) {
sprintf(t, "Do It", i);
addtopup(menu, t);
}
for (num = 0, scan = b->popup; scan != NULL; num++, scan = scan->next) {
sprintf(t, "%s%%x%d", scan->title, num + 2);
addtopup(menu, t);
}
i = dopup(menu);
freepup(menu);
if (i == 1) { /* Execute button */
/* DO IT selected from menu (MKK, 12/13/91) */
doit_bf_fly();
} else if ((i > 1) && (i <= num + 1)) {
for (num = 0, scan = b->popup; num != (i - 2);
num++, scan = scan->next); /* Keep on scanning... */
do_action(scan->action);
}
}
void selectdraw()
{
doclear();
draw_buttons(current_buttons);
draw_highlighted_button(which_button(
getvaluator(MOUSEX), getvaluator(MOUSEY)));
swapbuffers();
}
void flyindraw()
{
static float t = 1.0;
t -= 0.02;
if (t <= 0.0) {
current_buttons = selected->forward;
selected = NULL;
flyinflag = 0;
t = 1.0;
curbackcolor = path->button->backcolor;
doclear();
draw_buttons(current_buttons);
} else {
doclear();
draw_buttons(current_buttons);
draw_selected_button(selected, t);
}
swapbuffers();
}
void flyoutdraw()
{
static float t = 0.0;
doclear();
t += 0.02;
if (t >= 1.0) {
t = 0.0;
selected = NULL;
flyoutflag = 0;
draw_buttons(current_buttons);
} else {
draw_buttons(current_buttons);
draw_selected_button(selected, t);
}
swapbuffers();
}
/*
* This is called to do whatever action is required when a button is
* pushed. It just mucks with the button given to it.
*/
push_button(selected)
button_struct *selected;
{
int needpipe;
FILE *fp;
extern char *getcwd();
if( tick < 2 ) /* This was added to */
return; /* eliminate double-clicks */
else /* (MKK, 4/25/90). */
tick = 0;
/* First, go into proper directory */
/* (execute .cd. command) */
if (selected->cwd != NULL) {
if (chdir(selected->cwd) != 0)
{
fprintf(stderr, "Buttonfly: problem with .cd. %s",
selected->cwd);
perror("");
}
free(selected->cwd);
}
selected->cwd = getcwd(NULL, 128);
/* Need to open a pipe if submenu == "-" */
if ((selected->submenu != NULL) &&
(strcmp(selected->submenu, "-") == 0))
needpipe = 1;
else
needpipe = 0;
/* First, figure out where we'll build submenus from */
fp = NULL;
if ((selected->action != NULL) && needpipe) {
/* This performs the action, saving output */
fp = popen(selected->action, "r");
} else if (selected->submenu != NULL) {
fp = fopen(selected->submenu, "r");
}
/* Now, do action */
if ((selected->action != NULL) && !needpipe) {
do_action(selected->action);
}
/* Ok, now build submenus if we can */
if (fp != NULL) {
selected->forward = load_buttons(fp);
if (needpipe)
pclose(fp);
else
fclose(fp);
}
}
draw_buttons(buttons)
button_struct *buttons;
{
if (!eightbit) {
lmbind(LIGHT1, 1);
lmbind(MATERIAL, 1);
}
/* lmbind(LIGHT2, 2); */
if (buttons)
do {
if (buttons != selected)
draw_button(buttons);
} while (buttons = buttons->next);
}
draw_button(button)
button_struct *button;
{
float r = 1.0, g = 1.0, b = 1.0;
pushmatrix();
if (!eightbit) {
tmp_mat[1] = tmp_mat[5] = button->color[0];
tmp_mat[2] = tmp_mat[6] = button->color[1];
tmp_mat[3] = tmp_mat[7] = button->color[2];
lmdef(DEFMATERIAL, 1, 0, tmp_mat);
}
translate(button->tx, button->ty, button->tz);
rotate(button->ax, 'x');
/* rotate(button->ay, 'y'); */
rotate(button->az, 'z');
draw_edge();
draw_front(button);
popmatrix();
}
draw_highlighted_button(button)
button_struct *button;
{
if (button) {
if (!eightbit) {
tmp_mat[1] = tmp_mat[5] = button->highcolor[0];
tmp_mat[2] = tmp_mat[6] = button->highcolor[1];
tmp_mat[3] = tmp_mat[7] = button->highcolor[2];
lmdef(DEFMATERIAL, 1, 0, tmp_mat);
}
pushmatrix();
translate(button->tx, button->ty, button->tz);
rotate(button->ax, 'x');
rotate(button->az, 'z');
draw_edge();
draw_front(button);
popmatrix();
}
}
draw_selected_button(button, t)
button_struct *button;
float t;
{
float gls, glc;
Angle ax, ay, az;
float tx, ty, tz;
int bc[3], i;
pushmatrix();
ax = (Angle) ((float) button->ax * t);
/* ay = (Angle)((float)button->ay*t); */
az = (Angle) ((float) button->az * t);
tx = t * button->tx;
ty = t * button->ty;
tz = t * button->tz;
translate(tx, ty, tz);
rotate(ax, 'x');
/* rotate(ay, 'y'); */
rotate(az, 'z');
if (!eightbit) {
if (flyinflag) { /* current high or current normal button colors */
tmp_mat[1] = tmp_mat[5] = button->highcolor[0];
tmp_mat[2] = tmp_mat[6] = button->highcolor[1];
tmp_mat[3] = tmp_mat[7] = button->highcolor[2];
} else {
tmp_mat[1] = tmp_mat[5] = button->color[0];
tmp_mat[2] = tmp_mat[6] = button->color[1];
tmp_mat[3] = tmp_mat[7] = button->color[2];
}
lmdef(DEFMATERIAL, 1, 0, tmp_mat);
}
draw_edge();
gl_sincos(ax - 900, &gls, &glc);
if (gls < glc * ty / (-tz + SCREEN + THICK)) {
/* draw back of button */
pushmatrix();
if (eightbit) {
int cm_cindex;
static int cm_toggle = 0;
/* toggle 2 indices for smooth gradation of button back */
cm_toggle = 1 - cm_toggle;
cm_cindex = CM_BUTTONBACKINDEX + cm_toggle;
/* set and map the color. note: bc already multiplied by 255 */
for (i = 0; i < 3; i++)
bc[i] = (int) (t * 255.0 + (1.0 - t) * cm_backcolor[i]);
/* to restore colors on inputchange. not REALLY needed now */
/* *(buttonmaparray + (cm_cindex * 3)) = bc[0];
/* *(buttonmaparray + (cm_cindex * 3 + 1)) = bc[1];
/* *(buttonmaparray + (cm_cindex * 3 + 2)) = bc[2];
*/
mapcolor(cm_cindex, (short) bc[0], (short) bc[1], (short) bc[2]);
color(cm_cindex);
} else {
for (i = 0; i < 3; i++)
bc[i] = (int)(t*255.0 + (1.0-t)*selected->backcolor[i]*255.0);
RGBcolor(bc[0], bc[1], bc[2]);
}
bgnpolygon();
v3f(back_polys[0][0]);
v3f(back_polys[0][1]);
v3f(back_polys[0][2]);
v3f(back_polys[0][3]);
endpolygon();
translate(0.0, 0.0, THICK);
translate(0.0, 0.0, SCREEN);
multmatrix(tv);
translate(0.0, 0.0, -SCREEN - THICK);
draw_buttons(button->forward);
popmatrix();
} else {
draw_front(button);
}
popmatrix();
}
button_struct *load_buttons(fp)
FILE *fp;
{
button_struct *scan;
int nb, i;
extern FILE *lex_fp;
extern button_struct *buttons_input;
lex_fp = fp;
yyparse();
nb = 0; /* Figure out how many buttons were made */
for (scan = buttons_input; scan != NULL; scan = scan->next)
++nb;
if (nb > MAX_SPOTS) {
fprintf(stderr,
"Buttonfly Warning: %d is too many buttons\n", nb);
fprintf(stderr, "(Maximum number is %d)\n", MAX_SPOTS);
return NULL;
}
i = 0; /* And now figure out where to put them */
for (scan = buttons_input; scan != NULL; scan = scan->next) {
scan->tx = spots[nb - 1][i + 0];
scan->ty = spots[nb - 1][i + 1];
scan->tz = spots[nb - 1][i + 2];
i += 3;
scan->ax = (int) (random(1.0) + 0.5) * 3600 - 1800;
scan->ay = 0;
scan->az = (int) (random(1.0) + 0.5) * 3600 - 1800;
}
return buttons_input;
}
stroke(str,xoffset,yoffset)
char *str;
float xoffset,yoffset;
{
register int i, mode;
pushmatrix();
translate(xoffset,yoffset,0.0);
for (; *str; str++) {
if (chrtbl[*str][0][0]) {
for (i=0; mode = chrtbl[*str][i][0]; i++) {
switch (mode) {
case 1:
translate((float)chrtbl[*str][i][1], (float)chrtbl[*str][i][2], 0.0);
break;
case 2:
bgnline();
v2i(&chrtbl[*str][i][1]);
break;
case 3:
v2i(&chrtbl[*str][i][1]);
break;
case 4:
v2i(&chrtbl[*str][i][1]);
endline();
break;
}
}
}
}
popmatrix();
}
draw_button_label(button)
button_struct *button;
{
if (eightbit) {
color(CM_TEXTINDEX);
} else {
RGBcolor(200, 200, 200);
}
scale(-0.015, 0.015, 0.015);
linewidth(sizex * 3 / 1000 + 1);
switch (button->wc) {
case 1:
stroke(button->name[0],
-6.0 * strlen(button->name[0]) / 2.0, -4.0, 0.0);
break;
case 2:
stroke(button->name[0],
-6.0 * strlen(button->name[0]) / 2.0, 1.0, 0.0);
stroke(button->name[1],
-6.0 * strlen(button->name[1]) / 2.0, -9.0, 0.0);
break;
case 3:
stroke(button->name[0],
-6.0 * strlen(button->name[0]) / 2.0, 6.0, 0.0);
stroke(button->name[1],
-6.0 * strlen(button->name[1]) / 2.0, -4.0, 0.0);
stroke(button->name[2],
-6.0 * strlen(button->name[2]) / 2.0, -14.0, 0.0);
break;
}
linewidth(1);
}
draw_button_label_tex(button)
button_struct *button;
{
float texfntwidth(char *);
static int once;
if (!once) {
static char *tfnt = "/usr/demos/data/images/Times-Italic.bw";
char *p, getenv(char *);
if (texfntinit((p = getenv("BUTTONFLY_FONT")) ? p : tfnt)< 0) {
have_texture = 0;
draw_button_label(button);
return;
}
once = 1;
}
if (eightbit) {
color(CM_TEXTINDEX);
} else {
RGBcolor(200, 200, 200);
}
scale(-0.015, 0.015, 0.015);
switch (button->wc) {
case 1:
texfntstroke(button->name[0],
-6.0 * texfntwidth(button->name[0]) / 2.0, -4.0, 0.0);
break;
case 2:
texfntstroke(button->name[0],
-6.0 * texfntwidth(button->name[0]) / 2.0, 1.5, 0.0);
texfntstroke(button->name[1],
-6.0 * texfntwidth(button->name[1]) / 2.0, -9.5, 0.0);
break;
case 3:
texfntstroke(button->name[0],
-6.0 * texfntwidth(button->name[0]) / 2.0, 6.5, 0.0);
texfntstroke(button->name[1],
-6.0 * texfntwidth(button->name[1]) / 2.0, -4.0, 0.0);
texfntstroke(button->name[2],
-6.0 * texfntwidth(button->name[2]) / 2.0, -14.5, 0.0);
break;
}
}
button_struct *which_button(mx, my)
int mx, my;
{
float x, y;
button_struct *button;
button = current_buttons;
if (button)
do {
x = (float) (mx - sizex / 2 - originx) / (float) sizex;
y = (float) (my - sizey / 2 - originy) / (float) sizey / 1.25;
x = x * (-button->tz + SCREEN + THICK * 2.0);
y = y * (-button->tz + SCREEN + THICK * 2.0);
if (button->tx - 0.625 < x && button->tx + 0.625 > x &&
button->ty - 0.5 < y && button->ty + 0.5 > y) {
return (button);
}
} while (button = button->next);
return (NULL);
}
add_button_to_path(current, button)
button_struct *current;
button_struct *button;
{
path_struct *step;
step = (path_struct *) malloc(sizeof(path_struct));
step->current_buttons = current;
step->button = button;
step->back = path;
path = step;
}
draw_edge()
{
int i;
if (!eightbit)
lmbind(LMODEL, 1);
for (i = 0; i < 8; i++) {
if (eightbit)
color(cm_buttoncolor[i]);
bgnpolygon();
n3f(edge_normals[i]);
v3f(edge_polys[i][0]);
v3f(edge_polys[i][1]);
v3f(edge_polys[i][2]);
v3f(edge_polys[i][3]);
endpolygon();
}
if (!eightbit)
lmbind(LMODEL, 0);
}
draw_front(button)
button_struct *button;
{
if (eightbit)
color(CM_BUTTONFRONT);
else
lmbind(LMODEL, 1);
bgnpolygon();
n3f(front_normals[0]);
v3f(front_polys[0][0]);
v3f(front_polys[0][1]);
v3f(front_polys[0][2]);
v3f(front_polys[0][3]);
endpolygon();
if (!eightbit)
lmbind(LMODEL, 0);
translate(0.0, 0.0, -THICK);
if (have_texture)
draw_button_label_tex(button);
else
draw_button_label(button);
}
void doclear()
{
if(eightbit)
color(CM_BACKINDEX);
else
c3f(curbackcolor);
clear();
}
/* ------- additional routines code for eight bitplane system ------ */
/* cm_map_button_colors sets up the color map for colorindex lighting of
buttons. Button material coefficients are extracted from the default
definition in .menu (rootbutton->defaults) and the default values in mat.
Lighting coefficients are extracted from the RGB definitions in light1,
light2, and light_model. See GT Graphics User's guide for a very poor
explanation on how to set up color ramp for lighting. See data.h for index
defines. Six indexes were used for normal button color and 6 for
highlighted button color. One index for background, two indexes for the
back of the button (to toggle for doublebuffer()) and one for the text
color. Eight bitplane system should dither between lighting indexes by
default.
*/
void cm_map_button_colors()
{
void cm_ramp();
float Cme[3], *Csa, *Cma, *Cla, *Cl, *Cmd, *Cms;
float diffuse[3], ambient[3], specular[3];
int i;
Cme[0] = Cme[1] = Cme[2] = 0.0; /* material->EMISSION */
Csa = &light_model[1]; /* light_model->AMBIENT */
Cma = &rootbutton->default_color[0]; /* material->AMBIENT */
Cla = &light1[1]; /* light->AMBIENT */
Cl = &light1[5]; /* light->LCOLOR */
Cmd = &rootbutton->default_color[0]; /* material->DIFFUSE */
Cms = &mat[9]; /* material->SPECULAR */
for (i = 0; i < 3; i++) {
ambient[i] = Cme[i] + *(Csa+i) * *(Cma+i) + *(Cla+i) * *(Cma+i);
diffuse[i] = ambient[i] + *(Cl+i) * *(Cmd+i);
specular[i] = diffuse[i] + *(Cl+i) * *(Cms+i);
if (ambient[i] > 1.0)
ambient[i] = 1.0;
if (diffuse[i] > 1.0)
diffuse[i] = 1.0;
if (specular[i] > 1.0)
specular[i] = 1.0;
}
/* map the colors ramps */
cm_ramp(CM_BUTTONINDEX, CM_BUTTONINDEX+CM_DIFFUSEOFFSET, ambient, diffuse);
cm_ramp(CM_BUTTONINDEX+CM_DIFFUSEOFFSET, CM_BUTTONINDEX+CM_SPECULAROFFSET,
diffuse, specular);
cm_backcolor[0] = (int) (rootbutton->backcolor[0] * 255.0 + 0.5),
cm_backcolor[1] = (int) (rootbutton->backcolor[1] * 255.0 + 0.5),
cm_backcolor[2] = (int) (rootbutton->backcolor[2] * 255.0 + 0.5);
mapcolor(CM_BACKINDEX, cm_backcolor[0], cm_backcolor[1], cm_backcolor[2]);
mapcolor(CM_BUTTONBACKINDEX, cm_backcolor[0], cm_backcolor[1],
cm_backcolor[2]);
mapcolor(CM_BUTTONBACKINDEX + 1, cm_backcolor[0], cm_backcolor[1],
cm_backcolor[2]);
mapcolor(CM_TEXTINDEX, 200, 200, 200);
}
/* cm_ramp builds a linear ramp between two colors within the colorindexes
given.
*/
void cm_ramp(lowindex, highindex, lowcolor, highcolor)
int lowindex, highindex;
float *lowcolor, *highcolor;
{
float r, g, b;
float rinc, binc, ginc;
int i;
if (highindex - lowindex == 0)
return;
r = *lowcolor;
g = *(lowcolor + 1);
b = *(lowcolor + 2);
rinc = (*highcolor - r) / (highindex - lowindex);
ginc = (*(highcolor + 1) - g) / (highindex - lowindex);
binc = (*(highcolor + 2) - b) / (highindex - lowindex);
for (i = lowindex; i < highindex; i++) {
mapcolor(i,(short)(r*255.0+0.5),(short)(g*255.0+0.5),
(short)(b*255.0+0.5));
r += rinc;
g += ginc;
b += binc;
}
}
/* This routine saves the color map entries from c1 to c2 in an array
called savearray. Savearray must be 3 time the number of color entries
to be saved times the the size os a short (3 * (c2 - c1) *
sizeof(short)).
*/
void cm_save_colormap(savearray,c1,c2)
short *savearray;
Colorindex c1, c2;
{
Colorindex i;
int n;
for (i = c1, n = 0; i <= c2; i++, n += 3) {
getmcolor(i, &savearray[n], &savearray[n + 1], &savearray[n + 2]);
}
}
/* This routine restores the color map entries c1 through c2 from
entries that have been stored in savearray. Restore_colormap is
intended to compliment save_colormap.
*/
/* void cm_restore_colormap(savearray,c1,c2) */
void cm_restore_colormap()
{
short *savearray = &buttonmaparray[0];
Colorindex c1 = 0, c2 = 15;
Colorindex i;
int n;
for (i = c1, n = 0; i <= c2; i++, n += 3) {
mapcolor(i, savearray[n], savearray[n + 1], savearray[n + 2]);
}
}
/* Restore news colors on exit */
void cm_restore_news_colors()
{
mapcolor(0, 0, 0, 0);
mapcolor(1, 255, 0, 0);
mapcolor(2, 0, 255, 0);
mapcolor(3, 255, 255, 0);
mapcolor(4, 0, 0, 255);
mapcolor(5, 255, 0, 255);
mapcolor(6, 0, 255, 255);
mapcolor(7, 255, 255, 255);
mapcolor(8, 85, 85, 85);
mapcolor(9, 198, 113, 113);
mapcolor(10, 113, 198, 113);
mapcolor(11, 142, 142, 56);
mapcolor(12, 113, 113, 198);
mapcolor(13, 142, 56, 142);
mapcolor(14, 56, 142, 142);
mapcolor(15, 170, 170, 170);
}
void add_tick()
{
tick++; /* Count number of timer events since last */
if(tick > 7200) tick = 2; /* left or middle mouse (MKK, 4/25/90). */
}
void doit_bf_fly()
{
short mx, my;
/* Flip the current button forward (MKK, 12/13/91). */
mx = getvaluator(MOUSEX);
my = getvaluator(MOUSEY);
if (flyinflag || flyoutflag) return;
selectflag = flyinflag = flyoutflag = FALSE;
selected = which_button(mx, my);
if (selected) {
push_button(selected);
if (selected->forward) {
add_button_to_path(current_buttons, selected);
flyinflag = TRUE;
} else {
if (path) chdir(path->button->cwd);
else chdir(rootbutton->cwd);
selected = NULL;
bf_redraw();
}
} else if (path) {
path_struct *step;
if( tick < 2 ) /* This was added to */
return; /* eliminate double-clicks */
else /* (MKK, 4/25/90). */
tick = 0;
flyoutflag = TRUE;
selected = path->button;
current_buttons = path->current_buttons;
step = path;
path = path->back;
free(step);
if (path) {
chdir(path->button->cwd);
curbackcolor = path->button->backcolor;
}
else {
chdir(rootbutton->cwd);
curbackcolor = rootbutton->backcolor;
}
}
}
/***** END OF FILE ***** END OF FILE ***** END OF FILE ***** END OF FILE *****/